﻿using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml.Serialization;
using DependencyAnalysis.Serialization;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace UnitTests
{
    [TestClass]
    public class XmlSerializableExpandoObjectTest
    {
        private dynamic _expandoObject;

        [TestInitialize]
        public void Initialize()
        {
            _expandoObject = new DataContractExpandoObject();
        }

        [TestMethod]
        public void PropertyCanBeAdded()
        {
            _expandoObject.Hello = "World";
            Assert.AreEqual("World", _expandoObject.Hello);
        }

        [TestMethod]
        public void PropertyValueCanBeSetTwice()
        {
            _expandoObject.Hello = "World";
            _expandoObject.Hello = 17;
            Assert.AreEqual(17, _expandoObject.Hello);
        }

        [TestMethod]
        public void CalculateWithProperty()
        {
            _expandoObject.Number = 123.4;
            _expandoObject.Number += 5;
            Assert.AreEqual(128.4, _expandoObject.Number);
        }

        [TestMethod]
        public void WhenGettingNotExistentMemberThenReturnNull()
        {
            Assert.IsNull(_expandoObject.NotExisting);
        }
    }

    [TestClass]
    public class XmlSerializableExpandoObjectTestXmlWriter
    {
        private StringBuilder _stringBuilder;
        private StringWriter _writer;
        private XmlSerializer _serializer;

        [TestInitialize]
        public void Initialize()
        {
            _stringBuilder = new StringBuilder();
            _writer = new StringWriter(_stringBuilder);
            _serializer = new XmlSerializer(typeof(XmlSerializableExpandoObject));
        }

        [TestMethod]
        public void NameIsSerializedAsAttribute()
        {
            dynamic expandoObject = new XmlSerializableExpandoObject { Name = "One", TypeName = "Two" };
            _serializer.Serialize(_writer, expandoObject);
            Assert.AreEqual("<?xml version=\"1.0\" encoding=\"utf-16\"?>" +
                            "\r\n<XmlSerializableExpandoObject Name=\"One\" TypeName=\"Two\" />", _stringBuilder.ToString());
        }

        [TestMethod]
        public void ScalarsAreSerializedAsElements()
        {
            dynamic expandoObject = new XmlSerializableExpandoObject { Name = "One", TypeName = "Two" };
            expandoObject.Hello = 2;
            _serializer.Serialize(_writer, expandoObject);
            Assert.AreEqual("<?xml version=\"1.0\" encoding=\"utf-16\"?>" +
                            "\r\n<XmlSerializableExpandoObject Name=\"One\" TypeName=\"Two\">\r\n" +
                            "  <Hello>2</Hello>\r\n" +
                            "</XmlSerializableExpandoObject>", _stringBuilder.ToString());
        }

        [TestMethod]
        public void ExpandosAreSerializedAsElements()
        {
            dynamic expandoObject = new XmlSerializableExpandoObject { Name = "One", TypeName = "Two" };
            expandoObject.Hello = new XmlSerializableExpandoObject { Name = "Three", TypeName = "Four" };
            _serializer.Serialize(_writer, expandoObject);
            Assert.AreEqual("<?xml version=\"1.0\" encoding=\"utf-16\"?>" +
                            "\r\n<XmlSerializableExpandoObject Name=\"One\" TypeName=\"Two\">\r\n" +
                            "  <Hello Name=\"Three\" TypeName=\"Four\" />\r\n" +
                            "</XmlSerializableExpandoObject>", _stringBuilder.ToString());
        }

        [TestMethod]
        public void EnumerationOfOneExpandoIsSerializedAsElements()
        {
            dynamic expandoObject = new XmlSerializableExpandoObject { Name = "One", TypeName = "Two" };
            expandoObject.Hello = new List<XmlSerializableExpandoObject>{
                new XmlSerializableExpandoObject { Name = "Three", TypeName = "Four" }};
            _serializer.Serialize(_writer, expandoObject);
            Assert.AreEqual("<?xml version=\"1.0\" encoding=\"utf-16\"?>" +
                            "\r\n<XmlSerializableExpandoObject Name=\"One\" TypeName=\"Two\">\r\n" +
                            "  <Hello>\r\n    <Four Name=\"Three\" TypeName=\"Four\" />\r\n" +
                            "  </Hello>\r\n" +
                            "</XmlSerializableExpandoObject>", _stringBuilder.ToString());
        }

        [TestMethod]
        public void EnumerationOfMultipleExpandoIsSerializedAsSequence()
        {
            dynamic expandoObject = new XmlSerializableExpandoObject { Name = "One", TypeName = "Two" };
            expandoObject.Hello = new List<XmlSerializableExpandoObject>{
                new XmlSerializableExpandoObject { Name = "Three", TypeName = "Four" },
                new XmlSerializableExpandoObject { Name = "Five", TypeName = "Six" },
            };
            _serializer.Serialize(_writer, expandoObject);
            Assert.AreEqual("<?xml version=\"1.0\" encoding=\"utf-16\"?>" +
                            "\r\n<XmlSerializableExpandoObject Name=\"One\" TypeName=\"Two\">\r\n" +
                            "  <Hello>\r\n" +
                            "    <Four Name=\"Three\" TypeName=\"Four\" />\r\n" +
                            "    <Six Name=\"Five\" TypeName=\"Six\" />\r\n" +
                            "  </Hello>\r\n" +
                            "</XmlSerializableExpandoObject>", _stringBuilder.ToString());
        }
    }
}
